package ihm.panel.info;

import ihm.applet.KrakenApplet;
import ihm.panel.PanelInterface;
import ihm.panel.TablePanel;
import tools.Logger;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.List;
import java.util.regex.PatternSyntaxException;

import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.RowFilter;
import javax.swing.event.TableModelEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;

import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import tools.AppletConstant;

import bdd.sql.server.bean.Log;

import enumTypes.LogType;

/**
 * Affiche les messages de log.
 * @author Guillaume Pocas & Jean-François Augé
 */
public class LoggerPanel extends TablePanel implements ActionListener, PanelInterface {

	private static final long serialVersionUID = 1L;

	private DefaultTableModel logger_atm;
	private JTable logger_jt;
	private TableRowSorter<DefaultTableModel> sorter;
	private static int MAX_LOG = 1000;
	
	private JPanel bottom_jp;
	
	private JButton filter_jb, export_jb, selectall_jb;
	private JTextField filter_jtf;

	private KrakenApplet applet;

	private static String[] COLUMN_NAMES = {"Date", "Type", "Machine", "Application", "Message"};
	private Object[][] column_content;

	/**
	 * Constructeur.
	 * @param applet
	 */
	public LoggerPanel(KrakenApplet applet) {
		this.applet = applet;
		initPanel();
	}
	
	@Override
	public void initPanel() {
				
		/*
		 * Table part!
		 */
		setLayout(new BorderLayout());
		logger_atm = new DefaultTableModel(populateModel(), COLUMN_NAMES);
		
		sorter = new TableRowSorter<DefaultTableModel>(logger_atm);
		
		logger_jt = new JTable(logger_atm) {
			private static final long serialVersionUID = 1L;

			//  Returning the Class of each column will allow different
			//  renderers to be used based on Class
			@SuppressWarnings({ "unchecked", "rawtypes" })
			public Class getColumnClass(int column) {
				return getValueAt(0, column).getClass();
			}

			//  Les quatre premières colonnes ne sont pas modifiables
			public boolean isCellEditable(int row, int column) {
				int modelColumn = convertColumnIndexToModel(column);
				return (modelColumn == 0 || modelColumn == 1
						|| modelColumn == 2 || modelColumn == 3
						|| modelColumn == 4) ? false : true;
			}
		};
		logger_jt.setPreferredScrollableViewportSize(logger_jt.getPreferredSize());
		logger_jt.setFillsViewportHeight(true);
		JScrollPane scrollPane = new JScrollPane(logger_jt);
		add(scrollPane, BorderLayout.CENTER);
		
		logger_jt.setRowSorter(sorter);

		/*
		 * Buttons part!
		 */
		bottom_jp = new JPanel();

		filter_jtf = new JTextField("");
		filter_jtf.setPreferredSize(AppletConstant.FIELD_SIZE);
		bottom_jp.add(filter_jtf);

		filter_jb = new JButton("Filtrer");
		filter_jb.addActionListener(this);
		filter_jb.setPreferredSize(AppletConstant.BUTTON_SIZE);
		bottom_jp.add(filter_jb);
		
		selectall_jb = new JButton("Tout sélectionner");
		selectall_jb.addActionListener(this);
		selectall_jb.setPreferredSize(AppletConstant.BUTTON_SIZE);
		bottom_jp.add(selectall_jb);

		export_jb = new JButton("Exporter");
		export_jb.addActionListener(this);
		export_jb.setPreferredSize(AppletConstant.BUTTON_SIZE);
		bottom_jp.add(export_jb);

		add(bottom_jp, BorderLayout.SOUTH);
	}
	
	@Override
	public void updateTableInfo() {
		setLocked(true);
		logger_atm.setDataVector(populateModel(), COLUMN_NAMES);
		setLocked(false);	
	}
	
	@Override
	public Object[][] populateModel() {
		if(applet.isUserLogged()){
			Session session = applet.getSession();
	
			String color = "";
			@SuppressWarnings("unchecked")
			List<Log> resultats = session.createCriteria(Log.class).addOrder(Order.desc("id")).add(Restrictions.ne("log_type_importance", LogType.Alert)).setMaxResults(MAX_LOG).list();
			
			column_content = new Object[resultats.size()][COLUMN_NAMES.length];
			
			int i, j = 0;
			for(i = 0; i < resultats.size(); i++) {
				//LogType type = resultats.get(i).getLog_type();
				LogType type = resultats.get(i).getLog_type_importance();
				if(type.equals(LogType.Error)){
					color = "red";
				}
				else if(type.equals(LogType.Warning)){
					color = "orange";
				}
				else	color = "blue";
				column_content[j][0] = "<html><font color=\'"+color+"\'>"+resultats.get(i).getLog_date()+"</font></html>";
				column_content[j][1] = "<html><font color=\'"+color+"\'>"+resultats.get(i).getLog_type_importance()+"</font></html>";
				column_content[j][2] = "<html><font color=\'"+color+"\'>"+resultats.get(i).getLog_type_equipement()+"</font></html>";
				//column_content[j][3] = "<html><font color=\'"+color+"\'>"+resultats.get(i).getLog_app()+"</font></html>";
				column_content[j][3] = "<html><font color=\'</font></html>";
				column_content[j][4] = "<html><font color=\'"+color+"\'>"+resultats.get(i).getLog_message()+"</font></html>";
				j++;
			}
			
			session.close();
			return column_content;
		}
		else	return null;
	}

	@Deprecated
	public void tableChanged(TableModelEvent e) {
		//ne doit pas arriver ici...
	}
	
	/**
	 * Filtre les logs.
	 */
	private void newFilter() {
	    RowFilter<DefaultTableModel, Object> rf = null;
	    //If current expression doesn't parse, don't update.
	    try {
	        rf = RowFilter.regexFilter(filter_jtf.getText());
	    } catch (PatternSyntaxException e) {
	        return;
	    }
	    sorter.setRowFilter(rf);
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource().equals(filter_jb)) {
			newFilter();
		}
		else if(e.getSource().equals(export_jb)) {
			if(logger_jt.getSelectedRowCount() > 0) {
				Object[][] obj = this.getSelectedRows(logger_jt.getSelectedRows()[0],
						logger_jt.getSelectedRows()[logger_jt.getSelectedRowCount()-1]);
				
				// parsing html tags
				for(int i=0; i<logger_jt.getSelectedRowCount(); i++) {
					for(int j=0; j<COLUMN_NAMES.length; j++) {
						obj[i][j] = ((String) obj[i][j]).replaceFirst("<html><font color='.*'>", "");
						obj[i][j] = ((String) obj[i][j]).replaceFirst("</font></html>", "");
						obj[i][j] = ((String) obj[i][j]).replaceFirst("<html><font color='", "");
					}
				}
				
				try {
					Logger.write(AppletConstant.LOG_FILE, obj, logger_jt.getSelectedRowCount(), COLUMN_NAMES.length);
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		}
		else if(e.getSource().equals(selectall_jb)) {
			logger_jt.selectAll();
		}
	}
	
	/**
	 * Retourne les champs selectionés.
	 * @param rowStart
	 * @param rowEnd
	 * @return the selected rows
	 */
	public Object[][] getSelectedRows(int rowStart, int rowEnd) {
		Object[][] selection = new Object[rowEnd-rowStart+1][COLUMN_NAMES.length];
		for(int i=0; i<rowEnd-rowStart+1; i++) {
			for(int j=0; j<COLUMN_NAMES.length; j++) {
				selection[i][j] = logger_atm.getValueAt(
						logger_jt.convertRowIndexToModel(rowStart+i),
						logger_jt.convertColumnIndexToModel(j));
				//System.out.print(selection[i][j]+"_");
			}
			//System.out.println();
		}
		return selection;
	}
	
	/**
	 * Retourne les cellules selectionées.
	 * @param rowStart
	 * @param rowEnd
	 * @return the selected rows
	 */
	@Deprecated
	 public Object[][] getSelectedCells(int rowStart, int rowEnd, int columnStart, int columnEnd) {
		Object[][] selection = new Object[rowEnd-rowStart+1][columnEnd-columnStart+1];
		for(int i=0; i<rowEnd-rowStart+1; i++) {
			for(int j=0; j<columnEnd-columnStart+1; j++) {
				selection[i][j] = logger_atm.getValueAt(
						logger_jt.convertRowIndexToModel(rowStart+i),
						logger_jt.convertColumnIndexToModel(columnStart+j));
				//System.out.print(selection[i][j]+" ");
			}
			//System.out.println();
		}
		return selection;
	}

}
